﻿/*********************************************************************************
**                                                                              **
**  Copyright (C) 2024 LiLong                                                   **
**  This file is part of GnssLogs.                                              **
**                                                                              **
**  GnssLogs is free software: you can redistribute it and/or modify            **
**  it under the terms of the GNU Lesser General Public License as published by **
**  the Free Software Foundation, either version 3 of the License, or           **
**  (at your option) any later version.                                         **
**                                                                              **
**  GnssLogs is distributed in the hope that it will be useful,                 **
**  but WITHOUT ANY WARRANTY; without even the implied warranty of              **
**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               **
**  GNU Lesser General Public License for more details.                         **
**                                                                              **
**  You should have received a copy of the GNU Lesser General Public License    **
**  along with GnssLogs.  If not, see <https://www.gnu.org/licenses/>.          **
**********************************************************************************/
#pragma once

#include "../TIME.h"
#include "LogHeaderDecoder.h"

namespace GnssLogs
{
namespace TIMEDecoder
{
using namespace tao::pegtl;
// clang-format off
using Sync      = TAO_PEGTL_STRING("#TIMEA");
using Header = LogHeaderDecoder::SyncExpression<Sync>;
struct ClockStatus : ascii::identifier {};
struct Offset : Floating {};
struct OffsetStd : Floating {};
struct UtcOffset : Floating {};
struct UtcYear : star<digit> {};
struct UtcMonth : star<digit> {};
struct UtcDay : star<digit> {};
struct UtcHour : star<digit> {};
struct UtcMin : star<digit> {};
struct UtcMs : star<digit> {};
struct UtcStatusRule : ascii::identifier {};
// clang-format on

using Expression = seq<Header,
                       ClockStatus,
                       Split,
                       Offset,
                       Split,
                       OffsetStd,
                       Split,
                       UtcOffset,
                       Split,
                       UtcYear,
                       Split,
                       UtcMonth,
                       Split,
                       UtcDay,
                       Split,
                       UtcHour,
                       Split,
                       UtcMin,
                       Split,
                       UtcMs,
                       Split,
                       UtcStatusRule,
                       one<'*'>,
                       CRC32,
                       Tail>;

template<typename T>
struct Action
{
};

template<>
struct Action<Header> : LogHeaderDecoder::LogHeaderHelperNoSetValue
{
};

template<>
struct Action<ClockStatus> : EnumHelper<Action<ClockStatus>, ClockModelStatus>
{
    static void setValue(TIME::Data& data, ClockModelStatus value) { data.clockStatus = value; }
};

template<>
struct Action<Offset> : DoubleHelper<Action<Offset>>
{
    static void setValue(TIME::Data& data, double value) { data.offset = value; }
};

template<>
struct Action<OffsetStd> : DoubleHelper<Action<OffsetStd>>
{
    static void setValue(TIME::Data& data, double value) { data.offsetStd = value; }
};

template<>
struct Action<UtcOffset> : DoubleHelper<Action<UtcOffset>>
{
    static void setValue(TIME::Data& data, double value) { data.utcOffset = value; }
};

template<>
struct Action<UtcYear> : IntHelper<Action<UtcYear>, uint32_t>
{
    static void setValue(TIME::Data& data, uint32_t value) { data.utcYear = value; }
};

template<>
struct Action<UtcMonth> : IntHelper<Action<UtcMonth>, uint8_t>
{
    static void setValue(TIME::Data& data, uint8_t value) { data.utcMonth = value; }
};

template<>
struct Action<UtcDay> : IntHelper<Action<UtcDay>, uint8_t>
{
    static void setValue(TIME::Data& data, uint8_t value) { data.utcDay = value; }
};

template<>
struct Action<UtcHour> : IntHelper<Action<UtcHour>, uint8_t>
{
    static void setValue(TIME::Data& data, uint8_t value) { data.utcHour = value; }
};

template<>
struct Action<UtcMin> : IntHelper<Action<UtcMin>, uint8_t>
{
    static void setValue(TIME::Data& data, uint8_t value) { data.utcMin = value; }
};

template<>
struct Action<UtcMs> : IntHelper<Action<UtcMs>, uint32_t>
{
    static void setValue(TIME::Data& data, uint32_t value) { data.utcMs = value; }
};

template<>
struct Action<UtcStatusRule> : EnumHelper<Action<UtcStatusRule>, UTCStatus>
{
    static void setValue(TIME::Data& data, UTCStatus value) { data.utcStatus = value; }
};

template<>
struct Action<CRC32> : CRC32Helper<Action<CRC32>>
{
    static void setValue(TIME::Data& data, uint32_t value) { data.crc32 = value; }
};
} // namespace TIMEDecoder
} // namespace GnssLogs